(function($){
	var KEY = "jforest.edit";
	
	var _IERANGE = !window.getSelection;
	
	function _escape(val) {
		return val.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
	}
	function _unescape(val) {
		return val.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&amp;/g, '&');
	}
	
	var Edit = function(options){
		this.options = $.extend({
			appendToEl:'',
			webRoot:'',
			loadCallback:function(){},
			changeCallback:function(){}
		},options);
		this._createIframe();
	};

	Edit.prototype = {
		_createIframe:function(){
			var opts = this.options,edit = this;
			this.$iframe = $('<iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" width="100%"></iframe>');
			this.$iframe.css('height','100%').appendTo(opts.appendToEl).on('load',function(){
				var doc = edit.getDoc();
				doc.designMode = 'on';
				$(doc.body).keyup(function(event){
					edit.options.changeCallback.apply(edit,[event]);
				});
				$(doc.body).html('');
				opts.loadCallback.apply(edit);
			});
			var doc = this.getDoc();
			doc.open();
			doc.write('<!DOCTYPE html><html lang="zh"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>'
				+'<link href='+opts.webRoot+'"/resources/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen"/>'
				+'<link href='+opts.webRoot+'"/resources/assets/bootstrap/css/bootstrap-theme.css" rel="stylesheet" media="screen"/>'
				+'<link href='+opts.webRoot+'"/resources/assets/font-awesome/css/font-awesome.min.css" rel="stylesheet" media="screen"/>'
				+'<base href="'+opts.webRoot+'" />'
				+'</head><body></body></html>');
			doc.close();
			return this
		},
		getDoc:function(){
			return this.$iframe[0].contentDocument || this.$iframe[0].contentWindow.document;
		},
		getWin:function(){
			var doc = this.getDoc();
			return doc.parentWindow || doc.defaultView;
		},
		getSelection:function(){	
			var doc = this.getDoc(),win = this.getWin();
			return _IERANGE ? doc.selection : win.getSelection();
		},
		getRange:function(){
			var sel = this.getSelection(),rng;
			try {
				if (sel.rangeCount > 0) {
					rng = sel.getRangeAt(0);
				} else {
					rng = sel.createRange();
				}
			}catch(e){}
			return rng; 
		},
		//加粗
		bold:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("Bold");opts.changeCallback.apply(this,['bold']);}catch(e){}}
		},
		//斜体
		italic:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("Italic");opts.changeCallback.apply(this,['italic']);}catch(e){}}
		},
		//设置字体大小
		fontSize:function(size){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("FontSize",false,size);opts.changeCallback.apply(this,['fontSize']);}catch(e){}}
		},
		//设置字体颜色
		foreColor:function(color){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("ForeColor",false,color);opts.changeCallback.apply(this,['foreColor']);}catch(e){}}
		},
		//设置背景颜色
		backColor:function(color){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("BackColor",false,color);opts.changeCallback.apply(this,['backColor']);}catch(e){}}
		},
		//居中对齐
		center:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("JustifyCenter");opts.changeCallback.apply(this,['center']);}catch(e){}}
		},
		//右对齐
		right:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("JustifyRight");opts.changeCallback.apply(this,['right']);}catch(e){}}
		},
		//左对齐
		left:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("JustifyLeft");opts.changeCallback.apply(this,['left']);}catch(e){}}
		},
		//拷贝选择的内容到剪贴板
		copy:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("Copy");opts.changeCallback.apply(this,['copy']);}catch(e){}}
		},
		indent:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("Indent");opts.changeCallback.apply(this,['indent']);}catch(e){}}
		},
		outdent:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("Outdent");opts.changeCallback.apply(this,['outdent']);}catch(e){}}
		},
		//包裹选中内容
		wrap:function(el){
			var rng = this.getRange(),opts=this.options;
			if(rng && rng.startOffset != rng.endOffset){
				try{
					var $node = $(el).html(rng.cloneContents());
					rng.deleteContents();
					rng.insertNode($node[0]);
					opts.changeCallback.apply(this,['wrap']);
				}catch(e){}
			}
		},
		//替换选中内容
		replace:function(val){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng && rng.startOffset != rng.endOffset){
				try{
					var node = doc.createTextNode(val);
					rng.deleteContents();
					rng.insertNode(node);
					opts.changeCallback.apply(this,['replace']);
				}catch(e){}
			}
		},
		//在光标处插入内容
		insert:function(val){
			if(val){
				var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
				if(rng){
					try{
						if(/<[^>]+>/g.test(val)){
							rng.insertNode($(val)[0]);
						}else{
							var node = doc.createTextNode(val);
							rng.insertNode(node);
						}
						opts.changeCallback.apply(this,['insert']);
					}catch(e){}
				}
			}
		},
		//删除选中内容, 不支持IE
		delRange:function(){
			var rng = this.getRange(),opts=this.options;
			if(rng){try{rng.deleteContents();opts.changeCallback.apply(this,['delRange']);}catch(e){}}
		},
		//移除格式化标签
		removeFormat:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("RemoveFormat");opts.changeCallback.apply(this,['removeFormat']);}catch(e){}}
		},
		//移除超链接
		unlink:function(){
			var rng = this.getRange(),doc = this.getDoc(),opts=this.options;
			if(rng){try{doc.execCommand("Unlink");opts.changeCallback.apply(this,['unlink']);}catch(e){}}
		},
		//获取所有内容
		html:function(val){
			var doc = this.getDoc();
			if(val){$(doc.body).html(val);return this;}
			else{return $(doc.body).html();}
		}
	};
	/* 编辑器外壳 */
	var EditShell = function(element,options){
		this.$textarea = $(element);
		this.options = $.extend({
			webRoot:'',
			height:null
		},options);
		
		this._createEl();
		var shell = this,opts = this.options;
		this.edit = new Edit({
			appendToEl:this.$el.find('.panel-body'),
			webRoot:opts.webRoot,
			loadCallback:function(){
				this.html(shell.$textarea.val());
				shell.syncHeight(this);
			},
			changeCallback:function(){
				shell.syncHeight(this);
				shell.$textarea.val(this.html());
			}
		});
		this.codeModal = new CodeModal({
			callback:function(type,text){
				shell.edit.insert('<pre class="prettyprint">'+_escape(text)+'</pre>');
				this.hide();
			}
		});
		
		this._createBtn();
	};

	EditShell.prototype = {
		_createEl:function(){
			var opts = this.options,parent = this.$textarea.parent();
			this.$el = $('<div class="panel panel-info"><div class="panel-heading"></div><div class="panel-body"></div></div>');
			var $body = this.$el.appendTo(parent).find('>.panel-body');
			this.$textarea.hide().appendTo($body).css('width','100%').css('height','100%');
			if(opts.height){
				$body.height(opts.height).niceScroll({styler:"fb",cursorcolor:"#d9edf7",
					cursorwidth:'6',cursorborderradius:'3',
					background:'#404040',spacebarenabled:false,cursorborder:'',zindex:'1000'});
			}
		},
		_createBtn:function(){
			var head = this.$el.find('.panel-heading'),edit=this.edit,shell=this;
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-file-text-o"></i></a>').click(function(){
				if(shell.isCodeView == false){
					shell.isCodeView = true;
					head.find('>a').hide();
					head.find('>span').hide();
					$(this).show();
				}else{
					shell.isCodeView = false;
					head.find('>a').show();
					head.find('>span').show();
					edit.html(shell.$textarea.val());
				}
				edit.$iframe.toggle();
				shell.$textarea.toggle();
			}).appendTo(head).tooltip({title:'源代码'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-bold"></i></a>').click(function(){
				edit.bold();}).appendTo(head).tooltip({title:'加粗'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-italic"></i></a>').click(function(){
				edit.italic();}).appendTo(head).tooltip({title:'斜体'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-align-left"></i></a>').click(function(){
				edit.left();}).appendTo(head).tooltip({title:'左对齐'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-align-center"></i></a>').click(function(){
				edit.center();}).appendTo(head).tooltip({title:'居中'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-align-right"></i></a>').click(function(){
				edit.right();}).appendTo(head).tooltip({title:'右对齐'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-eraser"></i></a>').click(function(){
				edit.removeFormat();}).appendTo(head).tooltip({title:'清除格式'});;
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-indent"></i></a>').click(function(){
				edit.indent();}).appendTo(head).tooltip({title:'缩进'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-outdent"></i></a>').click(function(){
				edit.outdent();}).appendTo(head).tooltip({title:'移除缩进'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-clipboard"></i></a>').click(function(){
				shell.codeModal.show();}).appendTo(head).tooltip({title:'代码录入'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-table"></i></a>').click(function(){
				edit.insert('<table border="1" class="table"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td></td><td></td></tr></tbody></table>');
			 }).appendTo(head).tooltip({title:'表格'});
			this._createTitleBtn(head);
			this._createUploadBtn(head);
		},
		_createTitleBtn:function(head){
			var edit=this.edit;
			var $span = $('<span class="dropdown"><a href="javascript:void(0);" style="padding:5px;" data-toggle="dropdown">'
				+'<i class="fa fa-h-square"></i></a><div class="dropdown-menu list-group" style="padding:0;"></div></span>')
					.appendTo(head).tooltip({title:'标题'});
			var $menu = $span.find('.dropdown-menu');
			$('<a href="javascript:void(0);" class="list-group-item">标题h1</a>').click(function(){edit.wrap('<h1></h1>');}).appendTo($menu);
			$('<a href="javascript:void(0);" class="list-group-item">标题h2</a>').click(function(){edit.wrap('<h2></h2>');}).appendTo($menu);
			$('<a href="javascript:void(0);" class="list-group-item">标题h3</a>').click(function(){edit.wrap('<h3></h3>');}).appendTo($menu);
			$('<a href="javascript:void(0);" class="list-group-item">标题h4</a>').click(function(){edit.wrap('<h4></h4>');}).appendTo($menu);
			$('<a href="javascript:void(0);" class="list-group-item">标题h5</a>').click(function(){edit.wrap('<h5></h5>');}).appendTo($menu);
		},
		_createUploadBtn:function(head){
			var shell=this,opts=this.options,edit=this.edit;
			this.$textarea.jfUpload($.extend({},opts.upload,{
				ui:false,
				callback:function(result){
					edit.insert('<img src="'+result.data+'"/>');
				}
			}));
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-upload"></i></a>').click(function(){
				shell.$textarea.jfUpload('upload')}).appendTo(head).tooltip({title:'上传图片'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-picture-o"></i></a>').click(function(){
				shell.$textarea.jfUpload('select')}).appendTo(head).tooltip({title:'插入图片'});
		},
		syncHeight:function(edit){
			//var $panelBody = this.$el.find('.panel-body');
			var height = $(edit.getDoc().body).height() + 30;
			if(height>edit.$iframe.height()){
				edit.$iframe.css('height',height);
				//$panelBody.height(height);
				//this.$el.height(height+60);
			}
			this.$textarea.css('height',edit.$iframe.height());
		}
	}
	
	$.fn.jfEdit = function(){
		var args = Array.prototype.slice.call(arguments, 0);
		var value = undefined;
		this.each(function () {
			var $this = $(this);
			if (args.length === 0 || typeof(args[0]) === "object") {
				opts = args.length === 0 ? {} : $.extend({}, args[0]);
				value = new EditShell(this,opts);  //创建控件
				$this.data(KEY,value);
			}else if (typeof(args[0]) === "string"){
				var entity = $this.data(KEY);
                if(entity === undefined){return;}
                value = entity[args[0]].apply(entity, args.slice(1));
			}else{
				 throw 'Invalid arguments to '+KEY+' plugin: ' + args;
			}
	    });
	    return (value === undefined) ? this : value;
	};
	
	$.fn.jfEdit.Constructor = EditShell;
	
	var CodeModal = function(options){
		this.options = $.extend({
			callback:function(text){}
		},options);
		var opts = this.options,cm = this;
		this.$el = $('<div class="modal fade" tabindex="-1"><div class="modal-dialog">'
				+'<div class="modal-content"><div class="modal-header clearfix"><button type="button" class="close" data-dismiss="modal">&times;</button>'
				+'<h4 class="modal-title col-sm-3">代码录入</h4><div class="col-sm-3"><select class="form-control">'
				+'<option value="xml">xml</option><option value="java">java</option>'
				+'</select></div></div><div class="modal-body"><textarea style="width:100%;height:370px;"></textarea></div>'
				+'<div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">取消</button>'
				+'<button type="button" class="btn btn-primary">确定</button></div></div></div></div>');
		this.$el.find('.btn-primary:first').click(function(){
			var text = cm.$el.find('.modal-body:first>textarea').val();
			var type = cm.$el.find('.modal-header:first select').val();
			opts.callback.apply(cm,[type,text]);
		});
	}
	CodeModal.prototype = {
		show:function(){
			this.$el.find('.modal-body:first>textarea').val('');
			this.$el.modal('show');
		},
		hide:function(){
			this.$el.modal('hide');
		}
	}
	
})(window.jQuery)